package gov.pbc.nn.kjgl.maintenance.view;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Session;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.orm.hibernate.ISessionCallback;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.annotation.Expose;
import com.bstek.dorado.core.Configure;
import com.bstek.dorado.data.entity.EntityState;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.dorado.uploader.DownloadFile;
import com.bstek.dorado.uploader.UploadFile;
import com.bstek.dorado.uploader.annotation.FileProvider;
import com.bstek.dorado.uploader.annotation.FileResolver;
import com.bstek.uflo.client.service.ProcessClient;
import com.bstek.uflo.client.service.TaskClient;
import com.bstek.uflo.model.ProcessInstance;
import com.bstek.uflo.model.task.Task;
import com.bstek.uflo.service.ProcessService;

import gov.pbc.nn.core.dao.CommonHibernateDao;
import gov.pbc.nn.core.dao.PbcnnCoreHibernateDao;
import gov.pbc.nn.core.utils.GetTableUtils;
import gov.pbc.nn.core.utils.MapUtils;
import gov.pbc.nn.kjgl.maintenance.entity.SysChange;
import gov.pbc.nn.kjgl.maintenance.entity.SysKnowledgeBase;
import gov.pbc.nn.kjgl.maintenance.entity.SysMaterial;
import gov.pbc.nn.kjgl.maintenance.entity.SysProblem;
import gov.pbc.nn.kjgl.maintenance.entity.SysProblemProcessing;
import gov.pbc.nn.kjgl.maintenance.handler.SysBusinessPeopleAssignmentHandler;
import gov.pbc.nn.uflo.UfloUtils;
import gov.pbc.nn.uflo.entity.Opinion;

@Component
public class SysProblemAuditPR {

	@Resource(name = CommonHibernateDao.BEAN_ID)
	private CommonHibernateDao hibernateDao;
	@Resource(name = PbcnnCoreHibernateDao.BEAN_ID)
	private PbcnnCoreHibernateDao coreHibernateDao;
	@Resource(name = ProcessClient.BEAN_ID)
	private ProcessClient pc;
	@Resource(name = TaskClient.BEAN_ID)
	private TaskClient tc;
	@Resource(name = ProcessService.BEAN_ID)
	private ProcessService processService;

	@DataProvider
	public SysProblem getProblem(String id) throws Exception {
		SysProblem problem = (SysProblem) this.hibernateDao.get(id, SysProblem.class);
		if (StringUtils.isNotEmpty(problem.getSchemeId())) {
			SysMaterial material = (SysMaterial) this.hibernateDao.get(problem.getSchemeId(), SysMaterial.class);
			problem = EntityUtils.toEntity(problem);
			EntityUtils.setValue(problem, "schemeName", material.getFileName());
		}
		return problem;
	}

	/**
	 * 业务主管部门领导审核时加载其部门内业务人员的意见（最新意见）
	 * 
	 * @return
	 */
	@DataProvider
	public List<Opinion> loadProblemYwyOpinion(Map<String, Object> params) {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String businessId = (String) params.get("businessId");
		Task task = this.tc.getTask(taskId);
		SysBusinessPeopleAssignmentHandler handler = ContextHolder.getBean(SysBusinessPeopleAssignmentHandler.BEAN_ID);
		List<String> users = handler.getBusinessPeople(businessId);
		List<Opinion> list = UfloUtils.getLatestOpinions(task.getProcessInstanceId(), businessId, "业务主管部门业务人员意见", null,
				users);
		return list;
	}

	/**
	 * 上传方案文件。
	 * 
	 * @param file
	 * @return
	 * @throws IOException
	 */
	@FileResolver
	@Transactional
	public Map<String, Object> uploadProblemSchemeFile(UploadFile file, Map<String, Object> params) throws IOException {
		Map<String, Object> result = new HashMap<String, Object>();
		String problemId = (String) params.get("id");
		String filename = file.getFileName();
		SysMaterial material = null;
		Path path = null;
		File dest = null;
		if (StringUtils.isEmpty(problemId)) {
			// 如果事件尚未保存，则将文件保存到临时文件目录
			path = Paths.get(ContextHolder.getBdfTempFileStorePath());
			dest = Files.createTempFile(path, null, null).toFile();
			file.transferTo(dest);
			result.put("tmpPath", dest.getAbsolutePath());
		} else {
			// 将文件保存到实际目录中
			path = Paths.get(Configure.getString("SYS_YUNWEI_FILE_UPLOAD_PATH"), "问题管理");
			if (!Files.exists(path)) {
				path = Files.createDirectories(path);
			}
			path = path.resolve(UUID.randomUUID().toString());

			SysProblem problem = (SysProblem) this.hibernateDao.get(problemId, SysProblem.class);
			material = new SysMaterial();
			material.setSysId(problem.getSysId());
			material.setSysName(problem.getSysName());
			material.setFileName(filename);
			material.setPath(path.toString());
			material.setType(5);// 文件类型：5，即问题相关
			this.hibernateDao.save(material);
			this.deleteSchemeFile(MapUtils.newHashMap(new String[] { "schemeId", "problemId" },
					new Object[] { problem.getSchemeId(), problemId }));
			problem.setSchemeId(material.getId());
			this.hibernateDao.update(problem);

			dest = Files.createFile(path).toFile();
			file.transferTo(dest);
			result.put("schemeId", problem.getSchemeId());
			result.put("schemeName", material.getFileName());
		}
		return result;
	}

	/**
	 * 上传知识库文件
	 * 
	 * @param file
	 * @param params
	 * @return
	 * @throws IOException
	 */
	@FileResolver
	@Transactional
	public Map<String, Object> uploadKnowledgeSchemeFile(UploadFile file, Map<String, Object> params)
			throws IOException {
		Map<String, Object> result = new HashMap<String, Object>();
		Path path = Paths.get(ContextHolder.getBdfTempFileStorePath());
		File dest = Files.createTempFile(path, null, null).toFile();
		file.transferTo(dest);
		result.put("tmpFilename", dest.getName());
		return result;
	}

	@Expose
	@Transactional
	public void deleteSchemeFile(Map<String, Object> params) throws IOException {
		String schemeId = (String) params.get("schemeId");

		final String problemId = (String) params.get("problemId");
		if (StringUtils.isNotEmpty(schemeId)) {
			SysMaterial ma = (SysMaterial) this.hibernateDao.get(schemeId, SysMaterial.class);
			if (ma != null) {
				String path = ma.getPath();
				this.hibernateDao.delete(ma);

				final String hql = "update " + SysProblem.class.getName() + " set schemeId=null where id=:problemId";
				this.hibernateDao.doInHibernateSession(new ISessionCallback<Void>() {

					@Override
					public Void doInSession(Session session) {
						session.createQuery(hql).setString("problemId", problemId).executeUpdate();
						return null;
					}

				});

				Files.deleteIfExists(Paths.get(path));
			}
		}
	}

	/**
	 * 下载方案文件
	 * 
	 * @param problemId
	 * @return
	 * @throws FileNotFoundException
	 */
	@FileProvider
	public DownloadFile downloadProblemSchemeFile(Map<String, Object> params) throws FileNotFoundException {
		String schemeId = (String) params.get("schemeId");
		SysMaterial ma = (SysMaterial) this.hibernateDao.get(schemeId, SysMaterial.class);
		String path = ma.getPath();
		File file = new File(path);
		DownloadFile df = new DownloadFile(file);
		df.setFileName(ma.getFileName());
		return df;
	}

	/**
	 * 运维人员完成任务，在该过程中操作人可能上传了方案文件.
	 * 
	 * @param problem
	 *            系统事件对象，前台提交的时候需要将修改前的数据一并提交
	 * @param taskId
	 * @throws IOException
	 */
	@DataResolver
	@Transactional
	public void completeTask(SysProblem problem, Map<String, Object> params) throws IOException {
		String taskId = (String) params.get("taskId");

		EntityState state = EntityUtils.getState(problem);
		if (state == EntityState.MODIFIED) {
			this.hibernateDao.update(problem);
		}
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("agree", 1);

		String flowName = problem.getChangeSys() ? "to 子流程" : (problem.getContinuity() ? "to 技术主管" : "to 结束");

		if (problem.getChangeSys()) {
			SysChange change = EntityUtils.getValue(problem, "sysChange");
			change.setDoDate(new Date());
			change.setFromProblem(true);
			this.hibernateDao.save(change);
			variables.put("sysChange", change);
			variables.put("cto", EntityUtils.getString(change, "cto"));
		} else {
			String cto = (String) params.get("cto");
			variables.put("cto", cto);
			variables.put("taskname", "【" + problem.getSysName() + "】系统问题，需技术主管审核");
		}
		this.tc.start(Long.parseLong(taskId));
		this.tc.complete(Long.parseLong(taskId), flowName, variables);
	}

	@Expose
	@Transactional
	public void completeTaskToYewu(Map<String, Object> params) {
		long taskId = Long.parseLong(params.get("taskId").toString());
		// boolean shouldYewu = true;
		String sysName = (String) params.get("sysName");
		Map<String, Object> variables = new HashMap<String, Object>();
		// variables.put("shouldYewu", shouldYewu);
		variables.put("taskname", "【" + sysName + "】系统问题，需业务主管部门人员给出意见");
		this.tc.start(taskId);
		this.tc.complete(taskId, "to 业务主管部门", variables);

	}

	/**
	 * 系统技术主管、运维部门主管审核
	 * 
	 * @param problem
	 * @param taskId
	 */
	@Expose
	@Transactional
	public void completeTask(Map<String, Object> params) {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		String businessId = (String) params.get("businessId");
		String cz = (String) params.get("cz");
		int agree = Integer.parseInt(params.get("agree").toString());
		String sysName = (String) params.get("sysName");

		Task task = this.tc.getTask(taskId);
		if (StringUtils.isNotEmpty(opinion)) {
			Opinion o = new Opinion();
			o.setBusKey(businessId);
			o.setBusTable(GetTableUtils.getTablename(SysProblem.class));
			o.setOpinion(opinion);
			o.setProcessInstanceId(task.getProcessInstanceId());
			o.setProcessName(SysProblemPR.PROCESS_NAME);
			o.setTaskId(taskId);
			o.setTaskName(task.getTaskName());
			o.setNodeName(task.getNodeName());
			o.setUsername(ContextHolder.getLoginUserName());
			o.setCname(ContextHolder.getLoginUser().getCname());
			o.setDeptId(ContextHolder.getLoginUser().getDepts().get(0).getId());
			o.setDeptName(ContextHolder.getLoginUser().getDepts().get(0).getName());
			this.coreHibernateDao.save(o);
		}
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("agree", agree);
		ProcessInstance processInstance = processService.getProcessInstanceById(task.getProcessInstanceId());
		String name = processService.getProcessVariable("taskname", processInstance).toString();
		if (StringUtils.isNotBlank(cz)) {
			variables.put("operationDeptLeader", cz);
			variables.put("taskname", "【" + sysName + "】系统问题，技术主管审核通过,请运维部门主管审核");
		} else {
			if (1 == agree) {
				if (name.equals("【" + sysName + "】系统问题，需业务主管部门人员给出意见")
						|| name.equals("【" + sysName + "】系统问题，业务主管部门处长审核不通过,重新给出意见")) {
					variables.put("taskname", "【" + sysName + "】系统问题，业务主管部门人员已给出意见,请业务主管部门处长审核");
				} else {
					variables.put("taskname", "【" + sysName + "】系统问题，运维部门主管审核通过");
				}
			} else if (0 == agree) {
				if (name.equals("【" + sysName + "】系统问题，运维部门主管审核不通过，需运维人员进行修改")) {
					variables.put("taskname", "【" + sysName + "】系统问题，运维部门主管审核不通过，需运维人员进行修改");
				} else if (name.equals("【" + sysName + "】系统问题，技术主管审核通过,请运维部门主管审核")) {
					variables.put("taskname", "【" + sysName + "】系统问题，运维部门主管审核不通过，需运维人员进行修改");
				} else {
					variables.put("taskname", "【" + sysName + "】系统问题，技术主管审核不通过,需运维人员进行修改");
				}
			}
			// else {
			// variables.put("taskname", "【" + sysName +
			// "】系统问题，技术主管审核不通过,需运维人员进行修改");
			// }
		}
		this.tc.start(taskId);
		this.tc.complete(taskId, variables);
	}

	/**
	 * 业务主管部门处长审核方案和部门业务员意见，完成任务
	 * 
	 * @param params
	 */
	@Expose
	@Transactional
	public void completeTaskByAuditOpinion(Map<String, Object> params) {
		long taskId = Long.parseLong(params.get("taskId").toString());
		String opinion = (String) params.get("opinion");
		String businessId = (String) params.get("businessId");
		int agree = Integer.parseInt(params.get("agree").toString());
		int backFlow = Integer.parseInt(params.get("backFlow").toString());
		Object backUsersObject = params.get("backUsers");
		List<String> backUsers = (List<String>) backUsersObject;
		Task task = this.tc.getTask(taskId);

		String sysName = (String) params.get("sysName");

		if (StringUtils.isNotEmpty(opinion)) {
			Opinion o = new Opinion();
			o.setBusKey(businessId);
			o.setBusTable(GetTableUtils.getTablename(SysProblem.class));
			o.setOpinion(opinion);
			o.setProcessInstanceId(task.getProcessInstanceId());
			o.setProcessName(SysProblemPR.PROCESS_NAME);
			o.setTaskId(taskId);
			o.setTaskName(task.getTaskName());
			o.setNodeName(task.getNodeName());
			o.setUsername(ContextHolder.getLoginUserName());
			o.setCname(ContextHolder.getLoginUser().getCname());
			o.setDeptId(ContextHolder.getLoginUser().getDepts().get(0).getId());
			o.setDeptName(ContextHolder.getLoginUser().getDepts().get(0).getName());
			this.coreHibernateDao.save(o);
		}

		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("agree", agree);
		variables.put("backFlow", backFlow);
		if (agree == 1 && backFlow == -1) {// 通过，给运维人员
			variables.put("taskname", "【" + sysName + "】系统问题，业务主管部门处长审核通过");
		} else if (0 == agree && 0 == backFlow) {// 退回本部们业务员
			variables.put("taskname", "【" + sysName + "】系统问题，业务主管部门处长审核不通过,重新给出意见");
		} else if (0 == agree && 1 == backFlow) {// 退回运维
			variables.put("taskname", "【" + sysName + "】系统问题，业务主管部门处长审核不通过,需运维人员进行修改");
		}
		variables.put("backUsers", backUsers);
		this.tc.start(taskId);
		this.tc.complete(taskId, variables);

	}

	/**
	 * 运维人员记录问题处置过程，完成任务，结束流程
	 * 
	 * @param problem
	 * @param processingList
	 * @param taskId
	 * @throws IOException
	 */
	@DataResolver
	@Transactional
	public void recordProblemProcessing(SysProblem problem, List<SysProblemProcessing> processingList,
			SysKnowledgeBase knowledge, String taskId) throws IOException {
		this.hibernateDao.update(problem);
		for (SysProblemProcessing processing : processingList) {
			this.hibernateDao.save(processing);
		}
		String tmpFilename = EntityUtils.getValue(knowledge, "tmpFilename");
		Path source = null;
		Path target = null;
		if (StringUtils.isNotBlank(tmpFilename)) {
			source = Paths.get(ContextHolder.getBdfTempFileStorePath(), tmpFilename);
			target = Paths.get(Configure.getString("SYS_YUNWEI_FILE_UPLOAD_PATH"), "问题管理");
			if (!Files.exists(target)) {
				target = Files.createDirectories(target);
			}
			target = target.resolve(UUID.randomUUID().toString());

			SysMaterial material = new SysMaterial();
			material.setSysId(problem.getSysId());
			material.setSysName(problem.getSysName());
			material.setFileName((String) EntityUtils.getValue(knowledge, "schemeName"));
			material.setPath(target.toString());
			material.setType(6);// 文件类型：5，即问题相关
			this.hibernateDao.save(material);

			knowledge.setSchemeId(material.getId());
		}
		this.hibernateDao.save(knowledge);

		this.tc.start(Long.parseLong(taskId));
		this.tc.complete(Long.parseLong(taskId), "to 结束");

		if (source != null && target != null) {
			Files.copy(source, target);
		}
	}
}
